package common;

import com.nx.fsm.action.FsmAction;
import com.nx.fsm.context.FsmContext;
import com.nx.fsm.context.FsmNodeResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 王向 2018/7/19
 */
public abstract class AbsOrderAction<T extends MyContext> implements FsmAction {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void check(FsmContext context) {
        T t = (T) context;
        try {
            logger.info("{} start check param opType={} orderId={}", t.getLogStr(), t.getOpType(), t.getRecordId());
            checkParams(t);
        } catch (RuntimeException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("校验参数失败{}", e.getMessage());
            } else {
                logger.info("校验参数失败: " + e.getMessage());
            }
            throw e;
        } catch (Throwable e) {
            logger.error("校验参数异常{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Override
    public void execute(FsmContext context, FsmNodeResult fsmNodeResult) {
        T t = (T) context;
        logger.info("{} start execute fsm opType={} orderId={}", t.getLogStr(), t.getOpType(), t.getRecordId());
        try {
            executeContext(t, fsmNodeResult);
            onSuccess(t, fsmNodeResult);
        } catch (RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            onError(t, fsmNodeResult, e);
            throw new RuntimeException(e);
        } finally {
            afterExecute(t, fsmNodeResult);
        }
    }

    /**
     * 校验参数的方法
     *
     * @param context context
     */
    protected abstract void checkParams(T context);

    /**
     * 执行业务逻辑的方法
     *
     * @param context       context
     * @param fsmNodeResult fsmNodeResult
     */
    protected abstract void executeContext(T context, FsmNodeResult fsmNodeResult);

    /**
     * 无论订单成功与否，都会执行的方法
     *
     * @param context       context
     * @param fsmNodeResult fsmNodeResult
     */
    protected void afterExecute(T context, FsmNodeResult fsmNodeResult) {
    }

    /**
     * 订单操作执行成功后的处理
     *
     * @param context       context
     * @param fsmNodeResult fsmNodeResult
     */
    protected void onSuccess(T context, FsmNodeResult fsmNodeResult) {
        // 统一追加订单操作MQ消息-父订单

    }

    /**
     * 订单操作执行失败的处理
     *
     * @param context       context
     * @param fsmNodeResult fsmNodeResult
     * @param e             e
     */
    protected void onError(T context, FsmNodeResult fsmNodeResult, Throwable e) {
        logger.error("执行状态机出现未知异常{}", e);
    }
}
